package upmc.fr.android.rss.actions;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import upmc.fr.android.model.Dictionary;
import upmc.fr.android.model.RSSArticle;
import upmc.fr.android.model.RSSFlow;
import upmc.fr.android.rss.actions.UserException.Errors;
import upmc.fr.android.rss.comparator.RSSArticleComparator;
import upmc.fr.android.rss.comparator.RSSFlowComparator;
import upmc.fr.android.rss.parser.IRSSFlowReader;
import upmc.fr.android.rss.parser.RSSFlowReader;
import upmc.fr.android.rss.parser.RSSReadingException;

public class UserActions2 implements IUserActions 
{
	private static IUserActions instance;
	private IRSSFlowReader reader = new RSSFlowReader();	
	private Dictionary dictionary;
	
	public static void main(String[] args) 
	{
		IUserActions actions = UserActions2.getInstance();
		String category = "Default";
		String url = "http://www.lemonde.fr/rss/une.xml";
		actions.addCategory(category);
		try
		{
			actions.addRSSFlow(category, url);
		}
		catch (UserException e) 
		{		
			e.printStackTrace();
		}
		for(RSSArticle a : actions.getAllArticles(true))
			System.out.println(a.getTitle() + " - " + a.getDate());
	}
	
	private UserActions2()
	{		
		dictionary = new Dictionary();
	}
	
	public static IUserActions getInstance()
	{
		if(instance == null)
			instance = new UserActions2();
		return instance;
	}
	
	public boolean exists(String category)
	{
		return this.dictionary.exists(category);
	}
	
	@Override
	public void addCategory(String category)
	{
		this.dictionary.addCategory(category);
	}

	@Override
	public void removeCategory(String category) 
	{
		this.dictionary.removeCategory(category);		
	}

	@Override
	public void addRSSFlow(String category, String url) throws UserException
	{
		try
		{			
			if(dictionary.exists(category, url))
				throw new UserException(Errors.EXISTING_FEED);			
						
			RSSFlow flow = reader.read(url);
			flow.setUrl(url);
			dictionary.addFeed(category, flow);			
		}
		catch(RSSReadingException e)
		{
			throw new UserException(Errors.INVALID_URL);
		}
	}

	@Override
	public void removeRSSFlow(String category, RSSFlow flow) 
	{
		if(dictionary.exists(category, flow))
			dictionary.removeFeed(category, flow);
	}
	
	@Override
	public List<RSSFlow> getFlows(String category) 
	{
		List<RSSFlow> result = new LinkedList<RSSFlow>();
		for(RSSFlow flow : dictionary.getFlows())
		{
			if(dictionary.getCategories(flow).contains(category))
				result.add(flow);			
		}	
		return result;
	}
	
	@Override
	public List<RSSFlow> getFlows(String category, RSSFlowComparator comparator) 
	{
		List<RSSFlow> result = getFlows(category);
		Collections.sort(result, comparator);
		return result;
	}	

	@Override
	public List<RSSArticle> getFeedArticles(RSSFlow flow, boolean includeHidden) 
	{		
		List<RSSArticle> result = null;
		result = includeHidden ? flow.getAllArticles() : flow.getVisibleArticles();		
		return result;
	}	
	
	@Override
	public List<RSSArticle> getFeedArticles(RSSFlow flow, RSSArticleComparator comparator, boolean includeHidden) 
	{		
		List<RSSArticle> result = null;
		result = getFeedArticles(flow, includeHidden);			
		Collections.sort(result, comparator);
		return result;
	}	
	
	@Override
	public List<RSSArticle> getAllArticles(boolean includeHidden)
	{
		List<RSSArticle> result = new LinkedList<RSSArticle>();
		for(RSSFlow feed : dictionary.getFlows())
		{
			if(includeHidden)
				result.addAll(feed.getAllArticles()); 
			else
				result.addAll(feed.getVisibleArticles());
		}
		return result;
	}

	@Override
	public List<RSSArticle> getAllArticles(RSSArticleComparator comparator, boolean includeHidden)
	{
		List<RSSArticle> result = getAllArticles(includeHidden);
		Collections.sort(result, comparator);
		return result;
	}

	@Override
	public void save() 
	{		
	}

	@Override
	public void update() throws RSSReadingException
	{		
		for(RSSFlow feed : dictionary.getFlows())
			reader.update(feed);
	}

	@Override
	public List<String> getCategories() 
	{
		return dictionary.getCategories();
	}

	@Override
	public void move(String category_source, String category_target, RSSFlow flow) 
	{		
		dictionary.move(category_source, category_target, flow);
	}	
	
	@Override
	public void setArticleRead(RSSArticle article, boolean read)
	{
		article.setRead(read);
	}

	@Override
	public void setArticleHidden(RSSArticle article, boolean hidden) 
	{
		article.setHidden(hidden);
	}
	
	@Override
	public RSSArticle getArticleByUrl(String url) 
	{
		for (RSSFlow flow : dictionary.getFlows())
			for(RSSArticle article : flow.getAllArticles())
			{
				if(article.getUrl().equals(url))
				{
					return article;
				}
			}
		return null;
	}

	@Override
	public void move(String source, String target)
	{
		List<RSSFlow> feeds = getFlows(source);
		for(RSSFlow feed : feeds)
			move(source, target, feed);		
	}

	@Override
	public void removeRSSFlow(String category, String url)
	{
		RSSFlow feed = dictionary.getFeed(url);
		removeRSSFlow(category, feed);
	}

	@Override
	public List<RSSArticle> getCategoryArticles(String category, RSSArticleComparator comparator, boolean includeHidden)
	{
		List<RSSFlow> flows = getFlows(category);		
		List<RSSArticle> result = new LinkedList<RSSArticle>();
		for(RSSFlow flow : flows)
			result.addAll(getFeedArticles(flow, includeHidden));
		Collections.sort(result, comparator);
		return result;
	}

	@Override
	public List<RSSArticle> getFeedArticles(String url, boolean includeHidden)
	{
		RSSFlow feed = dictionary.getFeed(url);
		return getFeedArticles(feed, includeHidden);
	}

	@Override
	public void move(String source, String target, String url)
	{
		RSSFlow feed = dictionary.getFeed(url);
		move(source, target, feed);
	}

	@Override
	public List<RSSArticle> getFeedArticles(String url, RSSArticleComparator comparator, boolean includeHidden)
	{
		RSSFlow feed = dictionary.getFeed(url);
		return getFeedArticles(feed,comparator, includeHidden);
	}

	@Override
	public void removeRssFeed(String category, String url)
	{
		RSSFlow feed = dictionary.getFeed(url);
		removeRSSFlow(category, feed);
	}		
}
